﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shapes.Geometry;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace ShapesExtensions
{
    /// <summary>
    /// A helpful class for Sprites
    /// </summary>
    public class Sprite : IDisposable, ITransformable2D
    {

        /// <summary>
        /// Gets the transformation which adjusts the sprite (position, origin, rotation, scale).
        /// </summary>
        public Transformation2D Transform { get { return _Transform; } }
        protected Transformation2D _Transform;


        public Vector2 Position { get { return _Transform.Position; } set { _Transform.Position = value; } }

        public Vector2 Origin { get { return _Transform.Origin; } set { _Transform.Origin = value; } }

        public Vector2 Scale { get { return _Transform.Scale; } set { _Transform.Scale = value; } }

        public Angle Rotation { get { return _Transform.Rotation; } set { _Transform.Rotation = value; } }

        /// <summary>
        /// Gets or sets the texture.
        /// </summary>
        public Texture2D Texture { 
            get { return _Texture; } 
            set { 
                _Texture = value;

                if (_SourceRectangle == null)
                    Transform.SetDimension(value.Width, value.Height);
            } 
        }
        Texture2D _Texture;

        /// <summary>
        /// Gets or sets the source rectangle. It defines the part of the texture which has to be displayed.
        /// </summary>
        public Rectangle? SourceRectangle { 
            get { return _SourceRectangle; } 
            set { 
                _SourceRectangle = value; 

                if(value != null)
                    Transform.SetDimension(value.Value.Width, value.Value.Height); 
            } 
        }
        Rectangle? _SourceRectangle = null;

        /// <summary>
        /// Indicates wether the Sprite is drawn or not
        /// </summary>
        public bool IsVisible { get { return _IsVisible; } set { _IsVisible = value; } }
        bool _IsVisible = true;

        /// <summary>
        /// Gets or sets the color.
        /// </summary>
        public Color Color { get { return _Color; } set { _Color = value; } }
        Color _Color = Color.White;

        /// <summary>
        /// Gets or sets the SpriteEffect of this Sprite, which indicates how it is mirrored.
        /// </summary>
        public SpriteEffects Flip { get { return _Flip; } set { _Flip = value; } }
        SpriteEffects _Flip = SpriteEffects.None;

        /// <summary>
        /// Gets or sets the layer depth.
        /// </summary>
        public float LayerDepth { get { return _LayerDepth; } set { _LayerDepth = value; } }
        float _LayerDepth = 0.5f;

        
        
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="texture">The texture.</param>
        public Sprite(Texture2D texture)
        {
            _Texture = texture;
            _Transform = new Transformation2D(Vector2.Zero, _Texture.Width, _Texture.Height);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="position">The position.</param>
        public Sprite(Texture2D texture, Vector2 position)
        {
            _Texture = texture;
            _Transform = new Transformation2D(position, _Texture.Width, _Texture.Height);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Sprite"/> class.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="position">The position.</param>
        /// <param name="sourceRectangle">The source rectangle.</param>
        public Sprite(Texture2D texture, Vector2 position, Rectangle sourceRectangle)
        {
            _Texture = texture;
            _Transform = new Transformation2D(position, _Texture.Width, _Texture.Height);
            _SourceRectangle = sourceRectangle;
        }

        #endregion

        /// <summary>
        /// Draws the sprite.
        /// </summary>
        /// <param name="batch">The SpriteBatch object ehich is used to draw.</param>
        public virtual void Draw(SpriteBatch batch)
        {
            if (!_IsVisible)
                return;

            batch.Draw(_Texture, _Transform.Position, _SourceRectangle, _Color, 
                _Transform.Rotation.ClockwiseRadians, _Transform.Origin, _Transform.Scale, _Flip, _LayerDepth); 
        }

        #region IDisposable Member

        public void Dispose()
        {
            this._Transform = null;
            this._Texture = null; // if the texture would be disposed, you could never use it again...
        }

        #endregion

    }
}
